#pragma once

#include <iostream>
#include <fstream>
#include <string>
#include <ctime>
#include <unistd.h>
#include <cstdarg>
#include <sys/types.h>
#include <pthread.h>
#include "LockGuard.hpp"

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
bool g_is_save = false;
const char *log_name = "log.txt";
// 日志等级
enum Level
{
    DEBUG = 0,
    INFO,
    WARNING,
    ERROR,
    FATAL
};

std::string LevelToString(int level)
{
    switch (level)
    {
    case DEBUG:
        return "Debug";
    case INFO:
        return "Info";
    case WARNING:
        return "Warning";
    case ERROR:
        return "Error";
    case FATAL:
        return "Fatal";
    default:
        return "Unknown";
    }
}

std::string GetTimeString()
{
    time_t curr_time = time(nullptr);
    struct tm *format_time = localtime(&curr_time);
    if (format_time == nullptr)
        return "None";

    char time_buffer[1024];
    snprintf(time_buffer, sizeof(time_buffer), "%d-%d-%d %d:%d:%d",
             format_time->tm_year + 1900,
             format_time->tm_mon + 1,
             format_time->tm_mday,
             format_time->tm_hour,
             format_time->tm_min,
             format_time->tm_sec);
    return std::string(time_buffer);
}

void SaveFile(const std::string &log_name, const std::string &message)
{
    std::ofstream out(log_name, std::ios::app);
    if (!out.is_open())
    {
        std::cerr << "Failed to open log file: " << log_name << std::endl;
    }
    out << message;
    out.close();
}

void LogMessage(std::string filename, int lineNo, bool is_save, int level, const char *format, ...)
{
    std::string level_string = LevelToString(level);
    std::string time_string = GetTimeString();
    // pthread_t self_id = pthread_self();
    pid_t self_id = getpid();


    // 获取格式化信息
    char buffer[1024];
    va_list arg;
    va_start(arg, format);
    vsnprintf(buffer, sizeof(buffer), format, arg);
    va_end(arg);

    std::string message = "[" + time_string + "]" + "[" + level_string + "]" +
                          "[pid:" + std::to_string(self_id) + "]" + "[" + filename + "]" +
                          "[" + std::to_string(lineNo) + "] " + buffer + "\n";
    // 输出之前加锁
    LockGruad lockGuard(&lock);
    if (!is_save) // 不保存，则输出到屏幕上
    {
        std::cout << message;
    }
    else // 保存，则输出到指定文件中
    {
        SaveFile(log_name, message);
    }
}

#define LOG(level, format, ...)                                                  \
    do                                                                           \
    {                                                                            \
        LogMessage(__FILE__, __LINE__, g_is_save, level, format, ##__VA_ARGS__); \
    } while (0)

#define EnableFile()  do  {  g_is_save = true; } while (0)


#define EnableScreen()  do  {  g_is_save = false; } while (0)